import { unref } from "vue";
import { ElsElemUtil,IElsElem } from "../ElsElem";
import {IElsForm} from "./inter"
import {has,get,set,isArray,isObject,unset,isBoolean} from "lodash-es"
import { treeMap,IUtilTree } from "../../utils/tree"
import Schema from 'async-validator';

//
const RULE_MESSAGE_TEMPLATE = {
  required: "请输入 [ {{label}} ] ！",
  pattern: "请按照要求输入正确的 [ {{label}} ] 格式! 格式：{{ pattern }}",
  common: "请输入正确的 [ {{label}} ] 格式!",
};

// 构建 elFormItem 的 props
const EL_FORM_ITEM_PROPS_KEYS = [
  "label",
  "labelWidth",
  "error",
  "showMessage",
  "inlineMessage",
  "required",
  "rules",
  "trigger",
  "message",
  "tip"
];
export namespace ElsFormUtil {
  // 依据 required 字段生成 rules 并和 rules 字段合并,如果 rules 中没有对应的 message 按照模板生成 对应的 message
  export const buildRules = (props: Record<string, any>) => {
    const required = unref(props.required) ?? false;
    const trigger = unref(props.trigger) ?? "blur";
    const message = has(props, "message")
      ? ElsElemUtil.getExpValue(unref(props.message), props)
      : ElsElemUtil.getExpValue(RULE_MESSAGE_TEMPLATE.required, props);
    const rules: Record<string, any>[] = isArray(unref(props.rules))
      ? [...unref(props.rules)]
      : [];
    // //
    const tks = Object.keys(RULE_MESSAGE_TEMPLATE);
    const res: Record<string, any>[] = [];
    let hasRequired = false;
    rules.forEach((rule) => {
      const d = { ...unref(rule) };
      const k = tks.filter((k) => has(d, k))?.[0] || "common";
      const t: string =
        d.message || unref(props.message) || get(RULE_MESSAGE_TEMPLATE, k);
      d.message = ElsElemUtil.getExpValue(t, { ...props, ...d });
      if (has(d, "required")) {
        hasRequired = true;
      }
      if (!has(d, "trigger")) {
        d.trigger = trigger;
      }
      res.push(d);
    });
    //
    if (!hasRequired && required) {
      res.push({ required, message, trigger });
    }
    delete props.required;
    delete props.trigger;
    delete props.message;
    //
    return res;
  };

  export const buildElFormItemProps = (props: Record<string, any>) => {
    const elFormItem = unref(get(props, "elFormItem"));
    const keys = isArray(elFormItem)
      ? elFormItem
      : isObject(elFormItem)
      ? Object.keys(elFormItem)
      : [];
    const res: Record<string, any> = isObject(elFormItem)
      ? { ...elFormItem }
      : {};
    EL_FORM_ITEM_PROPS_KEYS.forEach((k) => {
      if (has(props, k) && !keys.includes(k)) {
        res[k] = get(props, k);
        unset(props, k);
      }
    });
    unset(props, "elFormItem");
    return res;
  };

  export const isNeedElFormItem = (e: IElsElem.Elem) => {
    const elFormItem: boolean | Record<string, any> =
      unref(e.elFormItem);
    // elFormItem
    if (isBoolean(elFormItem)) {
      return elFormItem;
    }
    return elFormItem?.enabled ?? true;
  };

  // 表单校验工具方法
  export const validateFormField = (rules:Record<string,any>[],data:Record<string,any>) => {

    return true;
  }
  export const valideForm = (data:Record<string,any>,column:IElsForm.Column,rule:Record<string,any[]> = {}) => {
    // 生成 rule ，获取数据，验证
    const config:IUtilTree.Config<IElsForm.ColumnItem> = {
      children:(node) => {
        const c = node.children || node.cls;
        if(c && Array.isArray(c)){
          return new Array().concat(c)
        }
        return []
      }
    }
    //
    const fd:Record<string,any> = {}
    const descriptor:Record<string,any[]> = {}
    const fn:IUtilTree.CallFn<IElsForm.ColumnItem> = (node,l,i,pn) => {
      if(!isObject(node)){
        return true;
      }
      //
      if(pn){
        const p = `${pn.$prop || pn.prop || ''}.${node.prop || ''}`
        node.$prop = p.split('.').filter(t => t).join('.')
      }else if(node.prop){
        node.$prop = node.prop
      }
      // const 
      // 是否带有 rules 规则
      if(node.prop && (node.required || node.rules || has(rule,node.$prop))){
        const rules = new Array().concat(buildRules(node),get(rule,node.$prop) || [])
        descriptor[node.$prop] = rules;
        const value = get(data,node.$prop) || node.value || node.defaultValue
        fd[node.$prop] = value;
      }
    }
    treeMap(column,fn,config)
    //
    const validator = new Schema(descriptor);
    return new Promise<{status:boolean,info:Record<string,any[]>,errors:any[]|null,fields:any}>((resolve) => {
      validator.validate(fd,(errors,fields) => {
        const status = (errors || []).length == 0;
        const info:Record<string,any[]> = {}
        for(const e of (errors || [])){
          const n = e.field || '';
          if(info[n]){
            info[n].push(e)
          }else{
            info[n] = [e]
          }
        }
        resolve({status,info,errors,fields})
      })
    })
    
  }

  // 自定义第三方表单组件
  export const SELF_FORM_NAMES = ["elsListForm"]
}